<template>
  <div ref="table" class="drag-tree-table">
    <div class="drag-tree-table-header">
      <column
        v-for="(item, index) in data.columns"
        :width="item.width"
        :flex="item.flex"
        :key="index" >
        <input
          v-if="item.type == 'checkbox'"
          class="checkbox"
          type="checkbox"
          @click="onCheckAll($event, item.onChange)">
        <span v-else>
          {{ item.title }}
        </span>
      </column>
    </div>
    <div :class="isDraing ? 'is-draging' : '' " class="drag-tree-table-body" @dragover="draging" @dragend="drop">
      <row
        v-for="(item, index) in data[custom_field.lists]"
        :columns="data.columns"
        :isdraggable="isdraggable"
        :model="item"
        :custom_field="custom_field"
        :on-check="onSingleCheckChange"
        :is-contain-children="isContainChildren"
        :key="index"
        depth="0"/>
    </div>
  </div>
</template>

<script>
import store from '../../store'
import row from './row.vue'
import column from './column.vue'
import space from './space.vue'
document.body.ondrop = function(event) {
  event.preventDefault()
  event.stopPropagation()
}
export default {
  name: 'DragTreeTable',
  components: {
    row,
    column,
    space
  },
  props: {
    isdraggable: {
      type: Boolean,
      default: true
    },
    data: Object,
    dataOther: Object,
    onDrag: Function
  },
  data() {
    return {
      treeData: [],
      dragX: 0,
      dragY: 0,
      dragId: '',
      targetId: '',
      ccc: '',
      whereInsert: '',
      isDraing: false,
      custom_field: {
        id: 'name',
        parent_id: 'parent_id',
        order: 'order',
        lists: 'lists',
        open: 'open',
        checked: 'checked'
      },
      onCheckChange: null,
      isContainChildren: false
    }
  },
  computed: {
    changeMemberTab() {
      return this.$store.getters.whereInsert
    }
  },
  watch: {
    changeMemberTab(val) {
      this.whereInsert = val
    }
  },
  mounted() {
    if (this.data.custom_field) {
      this.custom_field = Object.assign({}, this.custom_field, this.data.custom_field)
    }
    setTimeout(() => {
      this.data.columns.map((item) => {
        if (item.type === 'checkbox') {
          this.onCheckChange = item.onChange
          this.isContainChildren = item.isContainChildren
        }
      })
    }, 100)

    // this.setInitData(this.data[this.custom_field.lists])
  },
  methods: {
    getElementLeft(element) {
      var actualLeft = element.offsetLeft
      var current = element.offsetParent
      while (current !== null) {
        actualLeft += current.offsetLeft
        current = current.offsetParent
      }
      return actualLeft
    },
    getElementTop(element) {
      // 如果表格在容器中滚动，需要做特殊计算
      const scrollTop = this.$refs.table.parentElement.scrollTop
      var actualTop = element.offsetTop - scrollTop
      var current = element.offsetParent
      while (current !== null) {
        actualTop += current.offsetTop
        current = current.offsetParent
      }
      return actualTop
    },
    draging(e) {
      this.isDraing = true
      if (e.pageX === this.dragX && e.pageY === this.dragY) return
      this.dragX = e.pageX
      this.dragY = e.pageY
      this.filter(e.pageX, e.pageY)
      if (e.clientY < 100) {
        window.scrollTo(0, scrollY - 6)
      } else if (e.clientY > (document.body.clientHeight - 160)) {
        window.scrollTo(0, scrollY + 6)
      }
    },
    drop(event) {
      this.clearHoverStatus()
      this.resetTreeData()
      this.isDraing = false
    },
    filter(x, y) {
      var rows = document.querySelectorAll('.tree-row')
      this.targetId = undefined
      const dragOriginElementTop = this.getElementTop(window.dragParentNode)
      const dragOriginElementLeft = this.getElementLeft(window.dragParentNode)
      const dragW = dragOriginElementLeft + window.dragParentNode.clientWidth
      const dragH = dragOriginElementTop + window.dragParentNode.clientHeight
      if (x >= dragOriginElementLeft && x <= dragW && y >= dragOriginElementTop && y <= dragH) {
        // 当前正在拖拽原始块不允许插入
        return
      }
      for (let i = 0; i < rows.length; i++) {
        const row = rows[i]
        const rx = this.getElementLeft(row)
        const ry = this.getElementTop(row)
        const rw = row.clientWidth
        const rh = row.clientHeight
        if (x > rx && x < (rx + rw) && y > ry && y < (ry + rh)) {
          const diffY = y - ry
          const hoverBlock = row.children[row.children.length - 1]
          hoverBlock.style.display = 'block'
          var targetId = row.getAttribute('tree-id')
          store.dispatch('targetId', targetId)
          let whereInsert = ''
          var rowHeight = row.offsetHeight
          if (diffY / rowHeight > 3 / 4) {
            if (hoverBlock.children[2].style.opacity !== '0.5') {
              this.clearHoverStatus()
              hoverBlock.children[2].style.opacity = 0.5
            }
            whereInsert = 'bottom'
          } else if (diffY / rowHeight > 1 / 4) {
            if (hoverBlock.children[1].style.opacity !== '0.5') {
              this.clearHoverStatus()
              hoverBlock.children[1].style.opacity = 0.5
            }
            whereInsert = 'center'
          } else {
            if (hoverBlock.children[0].style.opacity !== '0.5') {
              this.clearHoverStatus()
              hoverBlock.children[0].style.opacity = 0.5
            }
            whereInsert = 'top'
          }
          store.dispatch('whereInsert', whereInsert)
          this.whereInsert = store.getters.whereInsert
        }
      }
    },
    clearHoverStatus() {
      var rows = document.querySelectorAll('.tree-row')
      for (let i = 0; i < rows.length; i++) {
        const row = rows[i]
        const hoverBlock = row.children[row.children.length - 1]
        hoverBlock.style.display = 'none'
        hoverBlock.children[0].style.opacity = 0.1
        hoverBlock.children[1].style.opacity = 0.1
        hoverBlock.children[2].style.opacity = 0.1
      }
    },
    resetTreeData() {
      this.targetId = store.getters.aaa
      // this.targetId = 'do_login'
      if (this.targetId === undefined) return
      const listKey = this.custom_field.lists
      // const parentIdKey = this.custom_field.parent_id
      const idKey = this.custom_field.id

      const newList = []
      const curList = this.data[listKey]
      const curOther = this.dataOther[listKey]
      const newOhterList = []
      const _this = this
      function pushData(curList, needPushList) {
        for (let i = 0; i < curList.length; i++) {
          const item = curList[i]
          var obj = _this.deepClone(item)
          // debugger
          obj[listKey] = []
          // debugger
          if (_this.targetId === item[idKey]) {
            const curDragItem = _this.getCurDragItem(_this.data[listKey], window.dragId)
            if (_this.whereInsert === 'top') {
              // curDragItem[parentIdKey] = item[parentIdKey]
              needPushList.push(curDragItem)
              needPushList.push(obj)
            } else if (_this.whereInsert === 'center') {
              // curDragItem[parentIdKey] = item[idKey]
              obj[listKey].push(curDragItem)
              needPushList.push(obj)
            } else {
              // curDragItem[parentIdKey] = item[parentIdKey]
              needPushList.push(obj)
              needPushList.push(curDragItem)
            }
          } else {
            if (window.dragId !== item[idKey]) {
              needPushList.push(obj)
            }
          }
          if (item[listKey] && item[listKey].length) {
            pushData(item[listKey], obj[listKey])
          }
        }
      }
      function pushDataOther(curList, needPushList) {
        for (let i = 0; i < curList.length; i++) {
          const item = curList[i]
          var obj = _this.deepClone(item)
          // debugger
          obj[listKey] = []
          if (_this.targetId === item[idKey]) {
            // debugger
            const curDragItem = _this.getCurDragItem(_this.data[listKey], window.dragId)
            if (_this.whereInsert === 'top') {
              // curDragItem[parentIdKey] = item[parentIdKey]
              needPushList.push(curDragItem)
              needPushList.push(obj)
            } else if (_this.whereInsert === 'center') {
              // curDragItem[parentIdKey] = item[idKey]
              obj[listKey].push(curDragItem)
              needPushList.push(obj)
            } else {
              // curDragItem[parentIdKey] = item[parentIdKey]
              needPushList.push(obj)
              needPushList.push(curDragItem)
            }
          } else {
            if (window.dragId !== item[idKey]) {
              needPushList.push(obj)
            }
          }
          if (item[listKey] && item[listKey].length) {
            pushDataOther(item[listKey], obj[listKey])
          }
        }
      }
      pushDataOther(curOther, newOhterList)
      pushData(curList, newList)
      // this.resetOrder(newList) // sort排序
      // this.resetOrder(newOhterList) // sort排序
      this.onDrag(newList, newOhterList) // 重新赋值
    },
    resetOrder(list) {
      const listKey = this.custom_field.lists
      for (var i = 0; i < list.length; i++) {
        list[i][this.custom_field.order] = i
        if (list[i][listKey] && list[i][listKey].length) {
          this.resetOrder(list[i][listKey])
        }
      }
    },
    deepClone(aObject) {
      if (!aObject) {
        return aObject
      }
      var bObject, v, k
      bObject = Array.isArray(aObject) ? [] : {}
      for (k in aObject) {
        v = aObject[k]
        bObject[k] = (typeof v === 'object') ? this.deepClone(v) : v
      }
      return bObject
    },
    getCurDragItem(lists, id) {
      var curItem = null
      const listKey = this.custom_field.lists
      const idKey = this.custom_field.id
      function getchild(curList) {
        for (let i = 0; i < curList.length; i++) {
          var item = curList[i]
          if (item[idKey] === id) {
            curItem = JSON.parse(JSON.stringify(item))
            break
          } else if (item[listKey] && item[listKey].length) {
            getchild(item[listKey])
          }
        }
      }
      getchild(lists)
      return curItem
    },
    onCheckAll(evt, func) {
      this.setAllCheckData(this.data[this.custom_field.lists], !!evt.target.checked)
      const checkedList = this.getCheckedList(this.data[this.custom_field.lists])
      func && func(checkedList)
    },
    // 单个CheckBox勾选触发
    onSingleCheckChange() {
      const checkedList = this.getCheckedList(this.data[this.custom_field.lists])
      this.onCheckChange && this.onCheckChange(checkedList)
    },
    // 根据flag批量处理数据
    setAllCheckData(curList, flag) {
      const listKey = this.custom_field.lists
      for (let i = 0; i < curList.length; i++) {
        var item = curList[i]
        this.$set(item, 'checked', flag)
        if (item[listKey] && item[listKey].length) {
          this.setAllCheckData(item[listKey], flag)
        }
      }
    },
    // 获取所有选中的行
    getCheckedList(lists) {
      const listKey = this.custom_field.lists
      var checkedList = []
      const deepList = this.deepClone(lists)
      function getchild(curList) {
        for (let i = 0; i < curList.length; i++) {
          var item = curList[i]
          if (item.checked) {
            checkedList.push(item)
          }
          if (item[listKey] && item[listKey].length) {
            getchild(item[listKey])
          }
        }
      }
      getchild(deepList)
      return checkedList
    }
  }
}
</script>

<style lang="scss">
.drag-tree-table{
  margin: 20px 0;
  color: #606266;
  width: 48%;
  font-size: 12px;
}
.drag-tree-table-header{
  display: flex;
  padding: 15px 10px;
  background: #f5f7fa;
  height: 66px;
  line-height: 36px;
  box-sizing: border-box;
  font-weight: 600;
}
.tree-icon-hidden{
  visibility: hidden;
}
.is-draging .tree-row:hover{
  background: transparent !important;
}
</style>
